#pragma once
#include <Windows.h>
#include "CyRoutine.h"

class CyDelegate_base
{
public:
	virtual BOOL Do(
		HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) const = 0;

	inline virtual ~CyDelegate_base() {};
};

/****************************************************************************/
template <class R> 
class CyDelegate : public CyDelegate_base
{
public:

	typedef BOOL (R::*Handler)(HWND hWnd,
		UINT message, WPARAM wParam, LPARAM lParam);

	// Parameter:
	// R	: the class contain the method you want to make delegate( e.g: A )
	// obj	: the pointer of an instance of that class ( e.g: A a = new A(); )
	// ptr	: the method pointer of that class ( e.g: &A::fA )
	//
	// e.g: 
	// A a;
	// CyDelegate<A, A::*fA> delegateA(a, &A::fA);
	// delegateA.Do(...);
	CyDelegate(R * obj, Handler ptr)
	{
		if (obj == NULL || ptr == NULL)
		{
			CY_THROW("obj and ptr cannot be null");
		}
		_obj = obj;
		_ptr = ptr;
	}

	// Invoke this fucking delegate
	BOOL Do(HWND hWnd,
		UINT message, WPARAM wParam, LPARAM lParam) const override
	{
		return (_obj->*_ptr)(hWnd, message, wParam, lParam);
	}

private:
	Handler _ptr;
	R * _obj;
};